package spring.cloud.tasks.executor.utils;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import spring.cloud.tasks.executor.utils.log.LogEvents;
import spring.cloud.tasks.executor.utils.log.LogUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
@Setter
@Getter
public class SystemEnvProperties {

    /**
     * <pre>
     * shell作业的结果回写的文件全路径（如果需要返回一些执行结果，只需要将结果写入该文件），JSON结构:
     *  {
     *    returnMsg: 返回消息内容
     *    errorGroup: 200=SUCCESS, 500/550: error
     *    returnCode: 自定义返回码,
     *    prop: {k:v} 属性对
     *  }
     * </pre>
     */
    public static final String NAME_VIP_SATURN_OUTPUT_PATH = "VIP_SATURN_OUTPUT_PATH";
    /**
     * Saturn Console URI.
     */
    public static final String NAME_VIP_SATURN_CONSOLE_URI = "VIP_SATURN_CONSOLE_URI";
    /**
     * Executor ZK Client session timeout
     */
    public static final String NAME_VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT_IN_SECONDS = "VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT";
    /**
     * Executor ZK Client connection timeout
     */
    public static final String NAME_VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT_IN_SECONDS = "VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT";
    /**
     * Executor ZK Client retry times
     */
    public static final String NAME_VIP_SATURN_ZK_CLIENT_RETRY_TIMES = "VIP_SATURN_ZK_CLIENT_RETRY_TIMES";
    public static final String NAME_VIP_SATURN_PRG = "VIP_SATURN_PRG";
    public static final String NAME_VIP_SATURN_LOG_OUTFILE = "VIP_SATURN_LOG_OUTFILE";
    // Just init the jobs that are in the groups, if the variable is configured
    public static final String NAME_VIP_SATURN_INIT_JOB_BY_GROUPS = "VIP_SATURN_INIT_JOB_BY_GROUPS";
    private static final String NAME_VIP_SATURN_MAX_NUMBER_OF_JOBS = "VIP_SATURN_MAX_NUMBER_OF_JOBS";
    private static final String NAME_VIP_SATURN_EXECUTOR_CLEAN = "VIP_SATURN_EXECUTOR_CLEAN";
    private static final String NAME_VIP_SATURN_DCOS_TASK = "VIP_SATURN_DCOS_TASK";
    private static final String NAME_VIP_SATURN_K8S_DEPLOYMENT = "VIP_SATURN_K8S_DEPLOYMENT";
    private static final String NAME_VIP_SATURN_SHUTDOWN_TIMEOUT = "VIP_SATURN_SHUTDOWN_TIMEOUT";
    private static final String NAME_VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING = "VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING";
    private static final String NAME_VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL_IN_SEC = "VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL";
    private static final String NAME_VIP_SATURN_NOHUPOUT_SIZE_LIMIT_IN_BYTES = "VIP_SATURN_NOHUPOUT_SIZE_LIMIT";
    // switch for disable job init failed alarm, false by default
    private static final String NAME_VIP_SATURN_DISABLE_JOB_INIT_FAILED_ALARM = "VIP_SATURN_DISABLE_JOB_INIT_FAILED_ALARM";
    /**
     * 每个域最大作业数量
     */
    public static int VIP_SATURN_MAX_NUMBER_OF_JOBS = 500;
    /**
     * Executor离线时，其zk节点信息是否被清理
     */
    public static boolean VIP_SATURN_EXECUTOR_CLEAN = Boolean.parseBoolean(System.getProperty(NAME_VIP_SATURN_EXECUTOR_CLEAN, System.getenv(NAME_VIP_SATURN_EXECUTOR_CLEAN)));
    public static String VIP_SATURN_CONTAINER_DEPLOYMENT_ID;
    /**
     * Executor优雅退出的全局默认超时时间（单位：精确到秒，默认1分钟）
     */
    public static long VIP_SATURN_SHUTDOWN_TIMEOUT = 60;
    public static int VIP_SATURN_SHUTDOWN_TIMEOUT_MAX = 5 * 60 - 10;
    public static String VIP_SATURN_CONSOLE_URI = trim(
            System.getProperty(NAME_VIP_SATURN_CONSOLE_URI, System.getenv(NAME_VIP_SATURN_CONSOLE_URI)));
    public static List<String> VIP_SATURN_CONSOLE_URI_LIST = new ArrayList<>();
    public static int VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT_IN_SECONDS = -1;
    public static int VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT_IN_SECONDS = -1;
    public static int VIP_SATURN_ZK_CLIENT_RETRY_TIMES = -1;
    public static boolean VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING = false;
    // For restart and dump
    public static boolean VIP_SATURN_ENABLE_EXEC_SCRIPT = Boolean.getBoolean("VIP_SATURN_ENABLE_EXEC_SCRIPT");
    public static String VIP_SATURN_PRG = System.getProperty(NAME_VIP_SATURN_PRG);
    public static String VIP_SATURN_LOG_OUTFILE = System.getProperty(NAME_VIP_SATURN_LOG_OUTFILE);
    // nohup file size checking by default is 600 seconds
    public static int VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL_IN_SEC = 600;
    // nohup max file size by default is 500 MB
    public static long VIP_SATURN_NOHUPOUT_SIZE_LIMIT_IN_BYTES = 500 * 1024 * 1024L;
    public static int VIP_SATURN_SESSION_TIMEOUT_IN_SECONDS_IN_UNSTABLE_NETWORK = 40;
    public static int VIP_SATURN_CONNECTION_TIMEOUT_IN_SECONDS_IN_UNSTABLE_NETWORK = 40;
    public static int VIP_SATURN_RETRY_TIMES_IN_UNSTABLE_NETWORK = 9;
    public static boolean VIP_SATURN_DISABLE_JOB_INIT_FAILED_ALARM = Boolean.parseBoolean(
            System.getProperty(NAME_VIP_SATURN_DISABLE_JOB_INIT_FAILED_ALARM,
                    System.getenv(NAME_VIP_SATURN_DISABLE_JOB_INIT_FAILED_ALARM)));

    //private static Logger log = LoggerFactory.getLogger(SystemEnvProperties.class);

    static {
        loadProperties();
    }

    public static void loadProperties() {
        String maxNumberOfJobs = System
                .getProperty(NAME_VIP_SATURN_MAX_NUMBER_OF_JOBS, System.getenv(NAME_VIP_SATURN_MAX_NUMBER_OF_JOBS));
        if (StringUtils.isNotBlank(maxNumberOfJobs)) {
            try {
                VIP_SATURN_MAX_NUMBER_OF_JOBS = Integer.parseInt(maxNumberOfJobs);
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        String shutdownTimeout = System
                .getProperty(NAME_VIP_SATURN_SHUTDOWN_TIMEOUT, System.getenv(NAME_VIP_SATURN_SHUTDOWN_TIMEOUT));
        if (StringUtils.isNotBlank(shutdownTimeout)) {
            try {
                VIP_SATURN_SHUTDOWN_TIMEOUT = Integer.parseInt(shutdownTimeout);
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }
        if (VIP_SATURN_SHUTDOWN_TIMEOUT > VIP_SATURN_SHUTDOWN_TIMEOUT_MAX) {
            VIP_SATURN_SHUTDOWN_TIMEOUT = VIP_SATURN_SHUTDOWN_TIMEOUT_MAX;
        }

        String dcosTaskId = System.getProperty(NAME_VIP_SATURN_DCOS_TASK, System.getenv(NAME_VIP_SATURN_DCOS_TASK));
        if (StringUtils.isNotBlank(dcosTaskId)) {
            VIP_SATURN_CONTAINER_DEPLOYMENT_ID = dcosTaskId;
        } else {
            VIP_SATURN_CONTAINER_DEPLOYMENT_ID = System
                    .getProperty(NAME_VIP_SATURN_K8S_DEPLOYMENT, System.getenv(NAME_VIP_SATURN_K8S_DEPLOYMENT));
        }

        String zkClientSessionTimeoutStr = System.getProperty(NAME_VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT_IN_SECONDS,
                System.getenv(NAME_VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT_IN_SECONDS));
        if (StringUtils.isNotBlank(zkClientSessionTimeoutStr)) {
            try {
                VIP_SATURN_ZK_CLIENT_SESSION_TIMEOUT_IN_SECONDS = Integer.parseInt(zkClientSessionTimeoutStr);
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        String zkClientConnectionTimeoutStr = System
                .getProperty(NAME_VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT_IN_SECONDS,
                        System.getenv(NAME_VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT_IN_SECONDS));
        if (StringUtils.isNotBlank(zkClientConnectionTimeoutStr)) {
            try {
                VIP_SATURN_ZK_CLIENT_CONNECTION_TIMEOUT_IN_SECONDS = Integer.parseInt(zkClientConnectionTimeoutStr);
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        String zkClientRetryTimes = System.getProperty(NAME_VIP_SATURN_ZK_CLIENT_RETRY_TIMES,
                System.getenv(NAME_VIP_SATURN_ZK_CLIENT_RETRY_TIMES));
        if (StringUtils.isNotBlank(zkClientRetryTimes)) {
            try {
                VIP_SATURN_ZK_CLIENT_RETRY_TIMES = Integer.parseInt(zkClientRetryTimes);
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        String useUnstableNetworkSettings = System.getProperty(NAME_VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING,
                System.getenv(NAME_VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING));
        if (StringUtils.isNotBlank(useUnstableNetworkSettings)) {
            VIP_SATURN_USE_UNSTABLE_NETWORK_SETTING = Boolean.parseBoolean(useUnstableNetworkSettings);
        }

        String checkNohupOutSizeInterval = System.getProperty(NAME_VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL_IN_SEC,
                System.getenv(NAME_VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL_IN_SEC));
        if (StringUtils.isNotBlank(checkNohupOutSizeInterval)) {
            try {
                int interval_in_sec = Integer.parseInt(checkNohupOutSizeInterval);
                if (interval_in_sec > 0) {
                    VIP_SATURN_CHECK_NOHUPOUT_SIZE_INTERVAL_IN_SEC = interval_in_sec;
                }
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        String noHupOutSizeLimit = System.getProperty(NAME_VIP_SATURN_NOHUPOUT_SIZE_LIMIT_IN_BYTES,
                System.getenv(NAME_VIP_SATURN_NOHUPOUT_SIZE_LIMIT_IN_BYTES));
        if (StringUtils.isNotBlank(noHupOutSizeLimit)) {
            try {
                long sizeLimit = Long.parseLong(noHupOutSizeLimit);
                if (sizeLimit > 0) {
                    VIP_SATURN_NOHUPOUT_SIZE_LIMIT_IN_BYTES = sizeLimit;
                }
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }

        Set<String> tempSet = new HashSet<>();
        String initJobByGroups = System
                .getProperty(NAME_VIP_SATURN_INIT_JOB_BY_GROUPS, System.getenv(NAME_VIP_SATURN_INIT_JOB_BY_GROUPS));
        if (StringUtils.isNotBlank(initJobByGroups)) {
            try {
                String[] split = initJobByGroups.split(",");
                for (String temp : split) {
                    if (StringUtils.isNotBlank(temp)) {
                        tempSet.add(temp.trim());
                    }
                }
            } catch (Throwable t) {
                LogUtils.error(log, LogEvents.ExecutorEvent.COMMON, t.getMessage(), t);
            }
        }


    }

    protected static String trim(String property) {
        if (property != null && property.length() > 0) {
            return property.trim();
        }
        return property;
    }

    public static void init() {
        if (VIP_SATURN_CONSOLE_URI != null) {
            String[] split = VIP_SATURN_CONSOLE_URI.split(",");
            if (split != null) {
                for (String tmp : split) {
                    tmp = tmp.trim();
                    if (!tmp.isEmpty()) {
                        VIP_SATURN_CONSOLE_URI_LIST.add(tmp);
                    }
                }
            }
        }
    }

}
